Search Results: "dpat"

10 October 2007

Martin F. Krafft: Packaging with Git

Introduction I gave a joint presentation with Manoj at Debconf7 about using distributed version control for Debian packaging, and I volunteered to do an on-line workshop about using Git for the task, so it's about time that I should know how to use Git for Debian packaging, but it turns out that I don't. Or well, didn't. After I made a pretty good mess out of the mdadm packaging repository (which is not a big problem as it's just ugly history up to the point when I start to get it right), I decided to get down with the topic and figure it out once and for all. I am writing this post as I put the pieces together. It's been cooking for a week, simply so I could gather enough feedback. I am aware that Git is not exactly a showcase of usability, so I took some extra care to not add to the confusion. It may be the first post in a series, because this time, I am just covering the case of mdadm, for which upstream also uses Git and where I am the only maintainer, and I shall pretend that I am importing mdadm to version control for the first time, so there won't be any history juggling. Future posts could well include tracking Subversion repositories with git-svn, and importing packages previously tracked therewith, but this ain't no promise! (well, that last post is already being drafted, but far from finished; you have been warned!) I realise that git-buildpackage exists, but imposes a rather strict branch layout and tagging scheme, which I don't want to adhere to. And gitpkg (Romain blogged about it recently), deserves another look since, according to its author, it does not impose anything on its user. But in any case, before using such tools (and possibly extending them to allow for other layouts), I'd really rather have done it by hand a couple of times to get the hang of it and find out where the culprits lie. Now, enough of the talking, just one last thing: I expect this blog post to change quite a bit as I get feedback. Changes shall be highlighted in bold typeface.
Setting up the infrastructure First, we prepare a shared repository on git.debian.org for later use (using collab-maint for illustration purposes), download the Debian source package we want to import (version 2.6.3+200709292116+4450e59-3 at time of writing, but I pretend it's -2 because we shall create -3 further down ), set up a local repository, and link it to the remote repository. Note that there are other ways to set up the infrastructure, but this happens to be the one I prefer, even though it's slightly more complicated:
$ ssh alioth
$ cd /git/collab-maint
$ ./setup-repository pkg-mdadm mdadm Debian packaging
$ exit
$ apt-get source --download-only mdadm
$ mkdir mdadm && cd mdadm
$ git init
$ git remote add origin ssh://git.debian.org/git/collab-maint/pkg-mdadm
$ git config branch.master.merge refs/heads/master
Now we can use git-pull and git-push, except the remote repository is empty and we can't pull from there yet. We'll save that for later. Instead, we tell the repository about upstream's Git repository. I am giving you the git.debian.org URL though, simply because I don't want upstream repository (which lives on an ADSL line) hammered in response to this blog post:
$ git remote add upstream-repo git://git.debian.org/git/pkg-mdadm/mdadm
Since we're using the upstream branch of the pkg-mdadm repository as source (and don't want all the other mess I created in that repository), we'll first limit the set of branches to be fetched (I could have used the -t option in the above git-remote command, but I prefer to make it explicit that we're doing things slightly differently to protect upstream's ADSL line).
$ git config remote.upstream-repo.fetch \
    +refs/heads/upstream:refs/remotes/upstream-repo/upstream
And now we can pull down upstream's history and create a local branch off it. The "no common commits" warning can be safely ignored since we don't have any commits at all at that point (so there can't be any in common between the local and remote repository), but we know what we're doing, even to the point that we can forcefully give birth to a branch, which is because we do not have a HEAD commit yet (our repository is still empty):
$ git fetch upstream-repo
warning: no common commits
[ ]
  # in the real world, we'd be branching off upstream-repo/master
$ git checkout -b upstream upstream-repo/upstream
warning: You appear to be on a branch yet to be born.
warning: Forcing checkout of upstream-repo/upstream.
Branch upstream set up to track remote branch
  refs/remotes/upstream-repo/upstream.
$ git branch
* upstream
$ ls   wc -l
77
Importing the Debian package Now it's time to import Debian's diff.gz remember how I pretend to use version control for package maintenance for the first time. Oh, and sorry about the messy file names, but I decided it's best to stick with real data in case you are playing along: Since we're applying the diff against version 2.6.3+200709292116+4450e59, we ought to make sure to have the repository at the same state. Upstream never "released" that version, but I encoded the commit ID of the tip when I snapshotted it: 4450e59, so we branch off there. Since we are actually tracking the git.debian.org pkg-mdadm repository instead of upstream, you can use the tag I made. Otherwise you could consider tagging yourself:
$ #git tag -s mdadm-2.6.3+200709292116+4450e59 4450e59
$ git checkout -b master mdadm-2.6.3+200709292116+4450e59
$ zcat ../mdadm_2.6.3+200709292116+4450e59-2.diff.gz   git apply
The local tree is now "debianised", but Git does not know about the new and changed files, which you can verify with git-status. We will split the changes made by Debian's diff.gz across several branches.
The idea of feature branches We could just create a debian branch, commit all changes made by the diff.gz there, and be done with it. However, we might want to keep certain aspects of Debianisation separate, and the way to do that is with feature branches (also known as "topic" branches). For the sake of this demonstration, let's create the following four branches in addition to the master branch, which holds the standard Debian files, such as debian/changelog, debian/control, and debian/rules:
  • upstream-patches will includes patches against the upstream code, which I submit for upstream inclusion.
  • deb/conffile-location makes /etc/mdadm/mdadm.conf the default over /etc/mdadm.conf and is Debian-specific (thus the deb/ prefix).
  • deb/initramfs includes the initramfs hook and script, which I want to treat separately but not submit upstream.
  • deb/docs similarly includes Debian-only documentation I add to the package as a service to Debian users.
If you're importing a Debian package using dpatch, you might want to convert every dpatch into a single branch, or at least collect logical units into separate branches. Up to you. For now, our simple example suffices. Keep in mind that it's easy to merge two branch and less trivial to split one into two. Why? Well, good question. As you will see further down, the separation between master and deb/initramfs actually makes things more complicated when you are working on an issue spanning across both. However, feature branches also bring a whole lot of flexibility. For instance, with the above separation, I could easily create mdadm packages without initramfs integration (see #434934), a disk-space-conscious distribution like grml might prefer to leave out the extra documentation, and maybe another derivative doesn't like the fact that the configuration file is in a different place from upstream. With feature branches, all these issues could be easily addressed by leaving out unwanted branches from the merge into the integration/build branch (see further down). Whether you use feature branches, and how many, or whether you'd like to only separate upstream and Debian stuff is entirely up to you. For the purpose of demonstration, I'll go the more complicated way.
Setting up feature branches So let's commit the individual files to the branches. The output of the git-checkout command shows modified files that have not been committed yet (which I trim after the first example); Git keeps these across checkouts/branch changes. Note that the ./debian/ directory does not show up as Git does not know about it yet (git-status will tell you that it's untracked, or rather: contains untracked files since Git does not track directories at all):
$ git checkout -b upstream-patches mdadm-2.6.3+200709292116+4450e59
M Makefile
M ReadMe.c
M mdadm.8
M mdadm.conf.5
M mdassemble.8
M super1.c
$ git add super1.c     #444682
$ git commit -s
  # i now branch off master, but that's the same as 4450e59 actually
  # i just do it so i can make this point 
$ git checkout -b deb/conffile-location master
$ git add Makefile ReadMe.c mdadm.8 mdadm.conf.5 mdassemble.8
$ git commit -s
$ git checkout -b deb/initramfs master
$ git add debian/initramfs/*
$ git commit -s
$ git checkout -b deb/docs master
$ git add RAID5_versus_RAID10.txt md.txt rootraiddoc.97.html
$ git commit -s
  # and finally, the ./debian/ directory:
$ git checkout master
$ chmod +x debian/rules
$ git add debian
$ git commit -s
$ git branch
  deb/conffile-location
  deb/docs
* master
  upstream
  upstream-patches
At this time, we push our work so it won't get lost if, at this moment, aliens land on the house, or any other completely plausible event of apocalypse descends upon you. We'll push our work to git.debian.org (the origin, which is the default destination and thus needs not be specified) by using git-push --all, which conveniently pushes all local branches, thus including the upstream code; you may not want to push the upstream code, but I prefer it since it makes it easier to work with the repository, and since most of the objects are needed for the other branches anyway after all, we branched off the upstream branch. Specifying --tags instead of --all pushes tags instead of heads (branches); you couldn't have guessed that! See this thread if you (rightfully) think that one should be able to do this in a single command (which is not git push refs/heads/* refs/tags/*)
$ git push --all
$ git push --tags
Done. Well, almost
Building the package (theory) Let's build the package. There seem to be two (sensible) ways we could do this, considering that we have to integrate (merge) the branches we just created, before we fire off the building scripts:
  1. by using a temporary (or "throw-away") branch off upstream, where we integrate all the branches we have just created, build the package, tag our master branch (it contains debian/changelog), and remove the temporary branch. When a new package needs to be built, we repeat the process.
  2. by using a long-living integration branch off upstream, into which we merge all our branches, tag the branch, and build the package off the tag. When a new package comes around, we re-merge our branches, tag, and build.
Both approaches have a certain appeal to me, but I settled for the second, for two reasons, the first of which leads to the second:
  1. When I upload a package to the Debian archive, I want to create a tag which captures the exact state of the tree from which the package was built, for posterity (I will return to this point later). Since the throw-away branches are not designed to persist and are not uploaded to the archive, tagging the merging commit makes no sense. Thus, the only way to properly identify a source tree across all involved branches would be to run git-tag $branch/$tagname $branch for each branch, which is purely semantic and will get messy sooner or later.
  2. As a result of the above: when Debian makes a new stable release, I would like to create a branch corresponding to the package in the stable archive at the time, for security and other proposed updates. I could rename my throw-away branch, if it still existed, or I could create a new branch and merge all other branches, using the (semantic) tags, but that seems rather unfavourable.
So instead, I use a long-living integration branch, notoriously tag the merge commits which produced the tree from which I built the package I uploaded, and when a certain version ends up in a stable Debian release, I create a maintenance branch off the one, single tag which corresponds to the very version of the package distributed as part of the Debian release. So much for the theory. Let's build, already!
Building the package (practise) So we need a long-living integration branch, and that's easier done than said:
$ git checkout -b build mdadm-2.6.3+200709292116+4450e59
Now we're ready to build, and the following procedure should really be automated. I thus write it like a script, called poor-mans-gitbuild, which takes as optional argument the name of the (upstream) tag to use, defaulting to upstream (the tip):
#!/bin/sh
set -eu
git checkout master
debver=$(dpkg-parsechangelog   sed -ne 's,Version: ,,p')
git checkout build
git merge $ 1:-upstream 
git merge upstream-patches
git merge master
for b in $(git for-each-ref --format='%(refname)' refs/heads/deb/*); do
  git merge -- $b
done
git tag -s debian/$debver
debuild   # will ignore .git automatically
git checkout master
Note how we are merging each branch in turn, instead of using the octopus merge strategy (which would create a commit with more than two parents) for reasons outlined in this post. An octopus-merge would actually work in our situation, but it will not always work, so better safe than sorry (although you could still achieve the same result). If you discover during the build that you forgot something, or the build script failed to run, just remove the tag, undo the merges, checkout the branch to which you need to commit to fix the issue, and then repeat the above build process:
$ git tag -d debian/$debver
$ git checkout build
$ git reset --hard upstream
$ git checkout master
$ editor debian/rules    # or whatever
$ git add debian/rules
$ git commit -s
$ poor-mans-gitbuild
Before you upload, it's a good idea to invoke gitk --all and verify that all goes according to plan:
screenshot of gitk after the above steps
When you're done and the package has been uploaded, push your work to git.debian.org, as before. Instead of using --all and --tags, I now specify exactly which refs to push. This is probably a good habit to get into to prevent publishing unwanted refs:
$ git push origin build tag debian/2.6.3+200709292116+4450e59-3
Now take your dog for a walk, or play outside, or do something else not involving a computer or entertainment device.
Uploading a new Debian version If you are as lucky as I am, the package you uploaded still has a bug in the upstream code and someone else fixes it before upstream releases a new version, then you might be in the position to release a new Debian version. Or maybe you just need to make some Debian-specific changes against the same upstream version. I'll let the commands speak for themselves:
$ git checkout upstream-patches
$ git-apply < patch-from-lunar.diff   #444682 again
$ git commit --author 'J r my Bobbio <lunar@debian.org>' -s
  # this should also be automated, see below
$ git checkout master
$ dch -i
$ dpkg-parsechangelog   sed -ne 's,Version: ,,p'
2.6.3+200709292116+4450e59-3
$ git commit -s debian/changelog
$ poor-mans-gitbuild
$ git push
$ git push origin tag debian/2.6.3+200709292116+4450e59-3
That first git-push may require a short explanation: without any arguments, git-push updates only the intersection of local and remote branches, so it would never push a new local branch (such as build above), but it updates all existing ones; thus, you cannot inadvertedly publish a local branch. Tags still need to be published explicitly.
Hacking on the software Imagine: on a rainy Saturday afternoon you get bored and decide to implement a better way to tell mdadm when to start which array. Since you're a genius, it'll take you only a day, but you do make mistakes here and there, so what could be better than to use version control? However, rather than having a branch that will live forever, you are just creating a local branch, which you will not publish. When you are done, you'll feed your work back into the existing branches. Git makes branching really easy and as you may have spotted, the poor-mans-gitbuild script reserves an entire branch namespace for people like you:
$ git checkout -b tmp/start-arrays-rework master
Unfortunately (or fortunately), fixing this issue will require work on two branches, since the initramfs script and hook are maintained in a separate branch. There are (again) two ways in which we can (sensibly) approach this:
  • create two separate, temporary branches, and switch between them as you work.
  • merge both into the temporary branch and later cherry-pick the commits into the appropriate branches.
I am undecided on this, but maybe the best would be a combination: merge both into a temporary branch and later cherry-pick the commits into two additional, temporary branches until you got it right, and then fast-forward the official branches to their tips:
$ git merge master deb/initramfs
$ editor debian/mdadm-raid                     #  
$ git commit -s debian/mdadm-raid
$ editor debian/initramfs/script.local-top     #  
$ git commit -s debian/initramfs/script.local-top
[many hours of iteration pass ]
[  until you are done]
$ git checkout -b tmp/start-arrays-rework-init master
  # for each commit $c in tmp/start-arrays-rework
  # applicable to the master branch:
$ git cherry-pick $c
$ git checkout -b tmp/start-arrays-rework-initramfs deb/initramfs
  # for each commit $c in tmp/start-arrays-rework
  # applicable to the deb/initramfs branch:
$ git cherry-pick $c
This is assuming that all your commits are logical units. If you find several commits which would better be bundled together into a single commit, this is the time to do it:
$ git cherry-pick --no-commit <commit7>
$ git cherry-pick --no-commit <commit4>
$ git cherry-pick --no-commit <commit5>
$ git commit -s
Before we now merge this into the official branches, let me briefly intervene and introduce the concept of a fast-forward. Git will "fast-forward" a branch to a new tip if it decides that no merge is needed. In the above example, we branched a temporary branch (T) off the tip of an official branch (O) and then worked on the temporary one. If we now merge the temporary one into the official one, Git determines that it can actually squash the ancestry into a single line and push the official branch tip to the same ref as the temporary branch tip. In cheap (poor man's), ASCII notation:
- - - O             >> merge T >>     - - - = - - OT
         - - T      >>  into O >>
This works because no new commits have been made on top of O (if there would be any, we might be able to rebase, but let's not go there quite yet; rebasing is how you shoot yourself in the foot with Git). Thus we can simply do the following:
$ git checkout deb/initramfs
$ git merge tmp/start-arrays-rework-initramfs
$ git checkout master
$ git merge tmp/start-arrays-rework-init
and test/build/push the result. Or well, since you are not an mdadm maintainer (We^W I have open job positions! Applications welcome!), you'll want to submit your work as patches via email:
$ git format-patch -s -M origin/master
This will create a number of files in the current directory, one corresponding for each commit you made since origin/master. Assuming each commit is a logical unit, you can now submit these to an email address. The --compose option lets you write an introductory message, which is optional:
$ git send-email --compose --to your@email.address <file1> <file2> < >
Once you've verified that everything is alright, swap your email address for the bug number (or the pkg-mdadm-devel list address). Thanks (in advance) for your contribution! Of course, you may also be working on a feature that you want to go upstream, in which case you'd probably branch off upstream-patches (if it depends on a patch not yet in upstream's repository), or upstream (if it does not):
$ git checkout -b tmp/cool-feature upstream
[ ]
when a new upstream version comes around After a while, upstream may have integrated your patches, in addition to various other changes, to give birth to mdadm-2.6.4. We thus first fetch all the new refs and merge them into our upstream branch:
$ git fetch upstream-repo
$ git checkout upstream
$ git merge upstream-repo/master
we could just as well have executed git-pull, which with the default configuration would have done the same; however, I prefer to separate the process into fetching and merging. Now comes the point when many Git people think about rebasing. And in fact, rebasing is exactly what you should be doing, iff you're still working on an unpublished branch, such as the previous tmp/cool-feature off upstream. By rebasing your branch onto the updated upstream branch, you are making sure that your patch will apply cleanly when upstream tries it, because potential merge conflicts would be handled by you as part of the rebase, rather than by upstream:
$ git checkout tmp/cool-feature
$ git rebase upstream
What rebasing does is quite simple actually: it takes every commit you made since you branched off the parent branch and records the diff and commit message. Then, for each diff/commit_message pair, it creates a new commit on top of the new parent branch tip, thus rewrites history, and orphans all your original commits. Thus, you should only do this if your branch has never been published or else you would leave people who cloned from your published branch with orphans.
If this still does not make sense, try it out: create a (source) repository, make a commit (with a meaningful commit message), branch B off the tip, make a commit on top of B (with a meaningful message), clone that repository and return to the source repository. There, checkout the master, make a commit (with a ), checkout B, rebase it onto the tip of master, make a commit (with a ), and now git-pull from the clone; use gitk to figure out what's going on.
So you should almost never rebase a published branch, and since all your branches outside of the tmp/* namespace are published on git.debian.org, you should not rebase those. But then again, Pierre actually rebases a published branch in his workflow, and he does so with reason: his patches branch is just a collection of branches to go upstream, from which upstream cherry-picks or which upstream merges, but which no one tracks (or should be tracking). But we can't (or at least will not at this point) do this for our feature branches (though we could treat upstream-patches that way), so we have to merge. At first, it suffices to merge the new upstream into the long-living build branch, and to call poor-mans-gitbuild, but if you run into merge conflicts or find that upstream's changes affect the functionality contained in your feature branches, you need to actually fix those. For instance, let's say that upstream started providing md.txt (which I previously provided in the deb/docs branch), then I need to fix that branch:
$ git checkout deb/docs
$ git rm md.txt
$ git commit -s
That was easy, since I could evade the conflict. But what if upstream made a change to Makefile, which got in the way with my configuration file location change? Then I'd have to merge upstream into deb/conffile-location, resolve the conflicts, and commit the change:
$ git checkout deb/conffile-location
$ git merge upstream
CONFLICT!
$ git-mergetool
$ git commit -s
When all conflicts have been resolved, I can prepare a new release, as before:
$ git checkout master
$ dch -i
$ dpkg-parsechangelog   sed -ne 's,Version: ,,p'
2.6.3+200709292116+4450e59-3
# git commit -s debian/changelog
$ poor-mans-gitbuild
# git push
$ git push origin tag debian/2.6.3+200709292116+4450e59-3
Note that Git often appears smart about commits that percolated upstream: since upstream included the two commits in upstream-patches in his 2.6.4 release, my upstream-patches branch got effectively annihilated, and Git was smart enough to figure that out without a conflict. But before you rejoice, let it be told that this does not always work.
Creating and using a maintenance branch Let's say Debian "lenny" is released with mdadm 2.7.6-1, then:
$ git checkout -b maint/lenny debian/2.7.6-1
You might do this to celebrate the release, or you may wait until the need arises. We've already left the domain of reality ("lenny" is not yet released), so the following is just theory. Now, assume that a security bug is found in mdadm 2.7.6 after "lenny" was released. Upstream is already on mdadm 2.7.8 and commits deadbeef and c0ffee fix the security issue, then you'd cherry-pick them into the maint/lenny branch:
$ git checkout upstream
$ git pull
$ git checkout maint/lenny
$ git cherry-pick deadbeef
$ git cherry-pick c0ffee
If there are no merge conflicts (which you'd resolve with git-mergetool), we can just go ahead to prepare the new package:
$ dch -i
$ dpkg-parsechangelog   sed -ne 's,Version: ,,p'
2.7.6-1lenny1
$ git commit -s debian/changelog
$ poor-mans-gitbuild
$ git push origin maint/lenny
$ git push origin tag debian/2.7.6-1lenny1
Future directions It should be trivial to create the Debian source package directly from the repository, and in fact, in response to a recent blog post of mine on the dispensability of pristine upstream tarballs, two people showed me their scripts to do it. My post also caused Joey Hess to clarify his position on pristine tarballs, before he went out to implement dpkg-source v3. This looks very promising. Yet, as Romain argues, there are benefits with simple patch management systems. Exciting times ahead! In addition to creating source packages from version control, a couple of other ideas have been around for a while:
  • create debian/changelog from commit log summaries when you merge into the build branch.
  • integrate version control with the BTS, bidirectionally:
    • given a bug report, create a temporary branch and apply any patches found in the bug report.
    • upon merging the temporary branch back into the feature branch it modifies, generate a patch, send it to the BTS and tag the bug report + pending patch.
And I am sure there are more. If you have any, I'd be interested to hear about them!
Wrapping up I hope this post was useful. Thank you for reading to the end, this was probably my longest blog post ever. I want to thank Pierre Habouzit, Johannes Schindelin, and all the others on the #git/freenode IRC channel for their tutelage. Thanks also to Manoj Srivastava, whose pioneering work on packaging with GNU arch got me started on most of the concepts I use in the above. And of course, the members of the the vcs-pkg mailing list for the various discussions on this subject, especially those who participated in the thread leading up to this post. Finally, thanks to Linus and Junio for Git and the continuously outstanding high level of support they give. If you are interested in the topic of using version control for distro packaging, I invite you to join the vcs-pkg mailing list and/or the #vcs-pkg/irc.oftc.net IRC channel. NP: Aphex Twin: Selected Ambient Works, Volume 2 (at least when I started writing )

28 September 2007

Clint Adams: A thrusting hit will never find

Once upon a time I proposed a DebConf talk about how to write zsh completion functions, but it was rejected. Accordingly, I didn't waste any time preparing materials for it, so I never have anything to throw at people when they ask for some kind of introduction. Here we have a fictitious program called arismom. Usage information from the fictitious manpage and the fictitious --help output is as follows:
Usage: arismom [OPTION]... [FILE]...
Do it Jersey style.
  -a, --all                       do all those things
  -b                              bubble
      --bounce                    bonuce
      --CoC=STYLE                 adhere to STYLE code of conduct
  -d, --debian=PACKAGE            dedicate actions to Debian PACKAGE
  -e, --ensqualm=USER             ensqualm USER first
  -t, --tempdir=DIRECTORY         spew temporary files into DIRECTORY
So let's cut to the quick. Create a file called _arismom somewhere in your function search path. This is described by the array $fpath. You can view its contents by typing print -l $fpath, and you can add a a directory to the beginning with fpath=(~/.zsh/scratch $fpath) or to the end with fpath+=(~/.zsh/scritch). For the purposes of this blog entry, we'll pretend you have a ~/.michaelbolton/squatch directory in your $fpath and that you are now editing ~/.michaelbolton/squatch/_arismom. The first line of the file, at the very tippy top, should read
#compdef arismom
This ensures that when the completion system boots up and finds your file, it will associate your function with the command arismom and complete options and arguments for it accordingly. Speaking of arguments, skip a line for aesthetic equilibrium, and invoke the _arguments utility function.
_arguments \
_arguments is sort of the cdbs of the zsh completion fleet. By the end of this blog entry, you'll have no idea how it works, and if you want to do anything particularly complex with it, you might encounter some resistance. For those of you unfamiliar with Z-Shell syntax or shell syntax in general, the trailing backslash means I'm a-gonna feed you a ton of information about the command-line interface to arismom. So tell it about the first option already.
  '(-a --all)' -a,--all '[do all those things]' \
To oversimplify, this declares that -a and --all are options which produce the identical behavior of do all those things . Specifically, the part in parentheses says to not complete either -a or --all when either -a or --all is already on the command-line. The part in braces is merely brace expansion; for that reason it is outside of the single quotes. If you're unfamiliar with brace expansion, try print '(alice)' bob,carnie '[wilson]' to see how it expands. Finally, the phrase in brackets is an explanation of the option, which may or may not be displayed depending on your configuration. Next, do a short option that has no long option equivalent.
  '-b[bubble]' \
A long option with no short option equivalent looks similar. Don't feel limited by upstream's inadequate descriptions, misspellings, or poor grammar.
  '--bounce[amplify bounce level according to X-la algorithm]' \
Some options take arguments. Now we use colons.
  '--CoC=[adhere to CoC]:CoC style:(mjg59 buxy ubuntu)' \
The first column is the same optspec by which you've been so excited thus far, and the part between the colons is the message or description of that which will be matched. The part after the last colon is the action; in this case you are specifying a list of possibilities within single parentheses. In most cases, you'll want to be more dynamic than a pre-defined list, and there are many helper functions all ready to serve you.
  '(-d --debian)' -d,--debian= '[dedicate actions to Debian package]:package:_deb_packages avail' \
_deb_packages is a function that completes Debian packages; it can take avail, installed, or uninstalled to restrict which set of packages it offers. In this case we want it to complete any package available from your sources.
  '(-e --ensqualm)' -e,--ensqualm= '[ensqualm user first]:user to ensqualm:_users' \
Here the _users function will complete usernames.
  '(-t --tempdir)' -t,--tempdir= '[spew]:temp dir:_files -/' \
Normally the _files function will complete files, but you can tell it that you only want directories with the -/ option. Finally, we want to cover all the remaining arguments (which according to the fictitious usage information is a list of files). In this case, you happen to believe that files with the .nj extension are to be completed.
  '*:NJ files:_files -g "*.nj"'
The -g option specifies a glob pattern to match files. Now the entire file should look like this.
#compdef arismom
_arguments \
  '(-a --all)' -a,--all '[do all those things]' \
  '-b[bubble]' \
  '--bounce[amplify bounce level according to X-la algorithm]' \
  '--CoC=[adhere to CoC]:CoC style:(mjg59 buxy ubuntu)' \
  '(-d --debian)' -d,--debian= '[dedicate actions to Debian package]:package:_deb_packages avail' \
  '(-e --ensqualm)' -e,--ensqualm= '[ensqualm user first]:user to ensqualm:_users' \
  '(-t --tempdir)' -t,--tempdir= '[spew]:temp dir:_files -/' \
  '*:NJ files:_files -g "*.nj"'
There you have it. Restart zsh and try tab-completing various things after arismom. P.S. I expect bug reports containing functions for dpatch-edit-patch, pkill, and pgrep by tomorrow morning. P.P.S. Why is Scott James Remnant still on Planet?

1 August 2007

Romain Francoise: Converting Debian packages from dpatch to quilt

I've been using quilt a lot at work recently (in a non-Debian environment), and I've been enjoying it very much. So much that I've decided to convert my Debian packages to it, from dpatch. Once you're used to quilt, using dpatch is almost literally painful. :)

There doesn't seem to be a ready-made guide on how to convert packages from dpatch to quilt, so here's how to do it painlessly in five easy steps:
  1. Install the quilt package (duh) and make sure that the QUILT_PATCHES variable is set to debian/patches in your shell environment. Or you can set it in your ~/.quiltrc file instead (see this post for other interesting settings).
  2. Delete the build dependency on dpatch from your debian/control file, replacing it with a dependency on quilt (>= 0.40).
  3. In your debian/rules file, include /usr/share/quilt/quilt.make instead of /usr/share/dpatch/dpatch.make.
  4. Convert all your dpatch files by using the following command from your package's top level:
    for p in $(dpatch list-all); do \
    quilt import -P $p.diff debian/patches/$p.dpatch; \
    quilt push; \
    done
  5. Delete dpatch files:
    rm -f debian/patches/00list debian/patches/*.dpatch
And that's pretty much it! You'll probably want to clean up the headers of your debian/patches/*.diff files since they'll still contain some dpatch markers. You can now build your package as usual. To edit a patch, use quilt push <patch>, quilt edit <file1> <file2>, finish with quilt refresh to save the patch.

For more information on how to use quilt, read the tutorial, it's in /usr/share/doc/quilt. You won't regret switching!

19 May 2007

Wouter Verhelst: Updating Debian/m68k patches for gcc 4.2

In a perfect world, software would work perfectly. Unfortunately... well, you know the drill. Since GCC 4.2 is upcoming, our resident GCC guy doko asked me to find someone to have a look at updating the Debian patches for GCC 4.1 so that they'd apply. Since I need to learn about GCC anyway for the Debian/ColdFire project (which nobody seems to be working on except for me), I started looking into it myself. The procedure is simple enough: uncomment lines in debian/rules.patch, and fix those m68k-specific patches that break. The first one was easy. debian/patches/m68k-gc.dpatch has been integrated upstream, so is no longer necessary. The second one was slightly more involved. But only slightly so; the patch tried to change libffi/src/m68k/sysv.S, which had received some three extra lines that conditionally add a .note.GNU-stack section. These three lines weren't there at first; but the .S file was otherwise entirely unchanged, so fixing this was rather easy. The next one is, uh, pretty hard. gcc/config/m68k/m68k.md is a file of 7k LOC in the GCC-specific "RTL" pseudo-assembly language, which I'm not at all familiar with. Yet, anyway. As a bonus, the first hunk in this file which fails to apply does so because that bit of this code has been changed rather significantly from GCC 4.1 to 4.2. Meaning:
  1. I need to figure out how this RTL code works
  2. I need to figure out what this particular RTL code block does
  3. I need to figure out what the point of this particular patch was
  4. I need to figure out how to write a patch (in RTL) which semantically does the same thing as what the original patch was doing. Without breaking the changes between 4.1 and 4.2
Wish me luck. At least the first two parts are almost finished; after skimming through chapters 12 and 14 of gccint.info, this hugging code almost makes sense to me. (oh, and if that last link doesn't make any sense to you, ask me for my fortune file at debconf) (which is in less than a month! whee! excitement!)

18 February 2007

Junichi Uekawa: Tokyo area debian meeting.

25th meeting was held yesterday.We did a session to compare and contrast dbs, quilt, and dpatch.Kobayashi was ill, and quilt session lacked a presentor. dbs session was presented by Iwamatsu, and I presented dpatch.quilt looks new but not much different from dpatch, dbs looks a bit old and rusty and less widely used now.The way forward looks more like integrated stg where dpatch-style stuff is more integrated into the SCM.

6 July 2006

Martin F. Krafft: Ubuntu and Debian

Ubuntu caused a lot of friction with and for Debian. In discussions with its founder, Mark Shuttleworth, and other Ubuntu developers during (and before) Debconf6, I was able to spell out the main criticisms from the Debian perspectives of the way Canonical/Ubuntu is handling things (without a claim to completeness). These criticisms mainly stem from discussions with fellow developers over the past 18 months, and I largely support all of them. I am publicising them here to help make the status quo more transparent. Before I go on, I want you to know that my neutral and somewhat even supportive stance towards Ubuntu has led many Debian folks to conclude that I must be a Canonical employee; I never was nor will be. Let's go:
  • A major point of friction I've gathered from many (Debian) sides stems from the fact that many developers are largely unsatisfied with how Canonical/Ubuntu cooperates and "gives back" to the Debian community: essentially, at the moment all we get are monolithic patches describing the differences between Debian packages and their Ubuntu counterparts. Even though Mark has claimed that the patches should be modular if the underlying package uses a modular package management system (such as dpatch), this does not seem to be the case at first glance (c.f. e.g. squid). You have to look inside the monolithic patch to note that its changes are compartementalised into dpatch files. Yet, Canonical/Ubuntu continuously claims to be "good" and to "give back" to the Debian community, but that's just not happening in that way. Canonical/Ubuntu either has to start giving back according to their own claims, or stop pretending that it does, and it's good that I have heard this voiced by one of the Canonical employees as well.

  • The perception that Canonical/Ubuntu is taking advantage of Debian seems to prevail. Taking advantage in this definition entails using but not giving back, as well as dragging integrative work out of Debian, something Joey Hess described as the supermarket thing, which has the potential to ruin the Debian project. Whether this is true or false, intentional or unintentional, it is important to recognize that these sentiments do exist among a number of members of the Debian community. There's a related point, namely jealousy about Ubuntu's success, and the fear that it steals Debian's users. In response, it is often said that while Ubuntu depends on Debian, the reverse is not the case: Debian does not need Ubuntu. This is false and true at the same time. Debian surely need derivatives like Ubuntu, for derivatives bring users, and users bring improvements and weight. However, Debian does not need any one derivative more than any other, and in fact it has been considered harmful if any derivative stands out.

  • Many of those with whom I've spoken perceive that Canonical/Ubuntu do not acknowledge Debian enough, nor give credit where credit is due. And this lack of credit and acknowledgement further amplifies the fear. Two examples seem to stand out:

    • The "universe" community that gathered around Ubuntu's core surprisingly often does not know about Debian, or do not know how Ubuntu and Debian relate. I do not have any data on this, unfortunately (see below). This is something to take up with the Ubuntu Community Council.

    • On the ubuntu.com front page, Debian is not mentioned at all; if you actually follow the About Ubuntu link, you can find Debian mentioned once in the first paragraph (albeit without a link), and if you did notice the right hand menu expanding, you may even decide to click on Ubuntu and Debian, where the relationship is finally illustrated from the Ubuntu point of view. To many, this is just not enough. Update (+6h): the About Ubuntu page now links to the Debian homepage. Thanks!

  • Canonical people, and Mark especially, draw an important line between Ubuntu (which is mostly free/open-source), and Canonical with its other products (Launchpad, Rosetta; which are non-free). However, from the outside, this line does not exist, or at least it appears as if there's a much stronger relationship between the Canonical and the Ubuntu project. This impression casts a corporate shadow over Ubuntu which deters many developers, even if it's undeniable that Ubuntu is a project of its own (to a large degree).

  • There's no question about Mark being on an agenda, for which he has assembled an impressively powerful team (which indirectly includes many Debian developers) at an (even more impressively) cheap cost. It's not my business to speculate about other people's finances, but those that do conclude that Mark is very likely not running too much of a risk with what he does at the moment and could basically pull out at any point in time. To some, who have dedicated large parts of their lives to Debian, this seems like an unwelcome way to play a game.

  • When Canonical entered the market and hired some developers to work on a Debian-related project, a lot of jealousy boiled up among those who didn't get a job, because back then it seemed that Canonical was out to pay people to work on Debian -- which is a common dream among us developers; at least people hoped that's what it would be. Many fundamental contributors felt left out and confronted with the question why they should continue their work for free when others are now getting paid for it. The twist is that nobody wanted to ask themselves that question, because money was never the reason why they started to work on Debian. The situation has leveled by now (I think). More and more people realise that Canonical is taking Ubuntu into a direction where many Debian developers do not want to go. Nevertheless, it seems that some of the frictions we are currently facing between Debian and Ubuntu still have their roots in the bad feelings from those times (which may well still exist in the individual case). Canonical/Ubuntu (and some Debian developers) need to realise (and get over) this, and somehow I think they've got a long way to go.

On Friday night of the Debconf6 conference, Mark assembled a bunch of people discuss the inter-project relationship. The (large) number of people who eventually joined, as well as the choice of venue (with live music) made the discussion somewhat awkward, but we did manage to get some good talking done, and I raised all of the above points. See the minutes of the meeting if interested. With their latest release out the door and a little more time on their hands (at least for a while), I hope that Canonical will follow up on the resolutions of the evening, as they have promised. The same goes for Debian, of course. There's very little Ubuntu can do about the jealousy other than acknowledge it, but it would be an important start. In addition, I hope to see all of the following take place rather sooner than later:
  • quality improvements to the patches they "give back" to Debian, and the adoption of a more appropriate medium of exchange. Instead of patches, active reaching out to the Debian developers by the Ubuntu developers would be even better in certain cases. The claim by Mark and one of his employees that this is simply impossible because of the commonly misconceived size of the paid body of developers (which is just too small) is really their challenge, and if they cannot meet it, maybe they have to go around it. It should be noted that efforts along these lines exist, so Canonical does not have to start from scratch. Note to Debian developers: if you're so inclined, please add your name to the bottom of that page.
  • a clear statement about how Canonical/Ubuntu plans to coexist or cooperate with Debian, and then the execution of those plans without leaving any doubt.
  • a survey of the Ubuntu community to gather (and publish) information about common perceptions of Debians position and role with respect to Ubuntu and vice versa. Again, this is something for the Ubuntu Community Council.
  • steps to ensure better familiarity with the Debian-Ubuntu situation among the Ubuntu community members.
  • a dedicated space for Debian people to go and be heard. Maybe the #debian-ubuntu channel on irc.debian.org will suffice, if some of the Canonical/Ubuntu higher-ups make an effort to keep an eye on it.
  • further steps by Canonical towards improving the relationship between the two projects, which could include regular meetings (or even irregular ones), uniting prominent representatives from both sides.
If I may add a thought that has come up lately (it's not only mine): a derivative like Ubuntu, namely one pushing Debian to the desktop, is an important asset for Debian. However, the only way this is going to work from the Debian perspective is as a mutual effort. If Canonical/Ubuntu do not realise this, maybe another derivative has to step in to fill the void? I hope this blog entry accomplishes what it tries, namely to shed some (more) light onto the relationship between Debian and Ubuntu, and to help the Canonical/Ubuntu side better understand the Debian perspective. Sorry for the length, I've worked on this entry ever since Debconf6 and despite a lot of editing (also by others; thank you!), it just wouldn't get shorter. Thanks for reading it all (assuming that's what you did if you arrived here). Update: this post has spread significantly, it seems. Thanks to all who've passed it on. I know of the following threads that ensued: If you find any others, please let me know.

29 June 2006

Amaya Rodrigo: Late, but Proud

Happy Yesterday! (Yesterday was the Pride day).

From Wikipedia: people should be proud of what they are, [...] sexual diversity is a gift, and [...] sexual orientation and gender identity are inherent and cannot be intentionally altered. Which I happen to agree with and celebrate.



This weekend we will skate through Madrid's streets, as there will be no cars in the centre, it will be a huge street party.

Info on activities for this year's Pride in Madrid, can be found here (in english, even).

5 April 2006

Clint Adams: Do I earn frequent blogger points by doing this?

Matthew,
1) I say "The Debian project believes that works under the GFDL, with invariant sections, are non-free". Someone is insulted, because they believe otherwise. Is my statement incorrect? Should that person feel insulted?
That statement would seem reasonable given the outcome of a project-wide General Resolution. If the individual believes that the process by which said outcome was reached was flawed beyond a reasonable point, that person might feel frustrated. If it is widely held that such was flawed beyond a reasonable degree, and the speaker advancing that position were widely regarded as being obviously deceptive, then that person should feel insulted.
2) I say "The Debian project believes that it is a shame that a member has died". Someone is insulted, because (for whatever reason) they disagree. Is my statement incorrect? Should that person feel insulted?
If you are basing your statement on a mailing list discussion in which no one was obliged to participate; which excluded anyone who didn't subscribe to that mailing list, anyone who refused to participate in said discussion for whatever reason, and anyone who quite correctly failed to recognize said discussion as a decision-making process; and which was generally shameful and embarrassing; then you are manufacturing consensus out of your ass. Yes, that statement is incorrect. Yes, we should all feel insulted. Trying to argue that we should just spout meaningless platitudes (no matter how strongly a tiny minority might mean them) at a whim is insane. The Debian project condemns the U.S. head of state for being a retard; everyone with whom I discussed this today agrees. I know that Debian's about technical excellence, but what harm can a simple political statement do? Maybe we should darken our website to show our support for those who died at the Gulf of Tonkin. If it's in poor taste to vote on whether or not the project believes something is a shame, then I think it's probably in poor taste to pretend that that was decided in some other manner.

13 February 2006

Joey Hess: patch followup

Followup on my previous review of Ubuntu's patches to my packages: So things have improved for my packages, at least after I made a stink about it and some people pretty clearly made it a priority to fix it. I doubt that this can be extrapolated to any other set of packages though. Total useful stuff gleaned this time: One minor build-depends fix, one icon.
Total estimated time to subit those to Debian BTS: approximatly 2 minutes.
Total time it took me to extract them from the diffs: about an hour.

15 December 2005

Junichi Uekawa: dpatch maintenance.

I've decided to play around with dpatch cleanups.Documentation updates, and syntactical fixes.Hopefully, nothing is broken with the minor changes.Testsuites are updated as well, and no major regression seems to exist.Currently, a lot of wishlist bugs exist against dpatch, many of them will become a maintenance overhead if applied as-is.An active contributor is really sought.

5 December 2005

Aigars Mahinovs: Another bug has pissed me enough to start debuggin...

Another bug has pissed me enough to start debugging. This time it is Totem-xine crashing on startup in Ubuntu dapper.

The first thing is that you cann't rebuild totem from sources multiple time after ubuntu patches - ubuntu uses dpatch to patch something in automake files and after the build has been run, the unpatch fails thus preventing a rebuild, doh! Worked around that by removing that patch. (Bug not reported yet)

After installing totem-gstreamer, my main suspect is the change to the statusbar, that look very recent. Could it be that Totem developers forgot a critical fix to the xine backend? Could it be that the treat xine backend as a ... second class citizen? To what? To that GStreamer? I tried to use GStreamer, I really did, but there are a few tiny issues: 1) it doesn't open even half the files that xine does, 2) within 5 minutes of a movie audio-video can easily get out of sync by 5 seconds. I have never seen A-V sync in xine. Ever. I love telling our Windows using frends that my movies "just work" with totem-xine, please do not take that away!

Anyway - back to the bug we go.

As we have a clean crash, I recompiled totem with debugging symbols ("DEB_BUILD_OPTS=nostrip,noopt debuild -us -uc") and run with gdb. When totem crashed, I got the code line, where it happened:
(totem:4608): GLib-GObject-WARNING **: invalid cast from   ' to  TotemTimeLabel'

Program received signal SIGSEGV, Segmentation fault.
0x08068659 in totem_time_label_set_time (label=0x8199a60, time=0, length=0) at totem-time-label.c:69
69 if (time / 1000 == label->priv->time / 1000

Now, that is interesting, lets see, what we have here - time is an int, so no segfaults from there, but label is a TotemTimeLabel. Hmm, that error now makes sense. And when we take a look at label->priv, it appears to be a pointer to TotemTimeLabelPrivate with an address of 0xffffffff. That's the problem, now we only need to backtrace trough the program and find the bug that is causing that.

Well all looks pretty nice - there is a "tick" event in the player that calls the time update. Not really clear, why there is such a discrepance between GtkLabel and TotemTimeLabel or why this structure is not inicialized in time. More strange is that gstreamer backend never calls this function. Wierd. Let's see what happens if I just return from it without doing anything. Does not help - now statusbar is crashing.

Let's try it from another angle - it worked before. Nothing much in totem changed since release of breezy. Installing the version from breezy, it works fine. Recompiling the version from breezy on dapper - crashes. Ouch! It looks like xine backend of totem has not been ported to that new crazy Gnome 2.12 thingie, like gstreamer backend was. Strange - that is a backend, it should not be dependent on the frontend, no? Anyway, it is not something I can do - I will have to install the breezy version, hack some dependencies to make it no conflict with one optional library and then file a critical bug on totem for breaking the xine backend.

But even that will have to wait 'till tomorrow, sleep is of the essence, anywere.

16 October 2005

Matthew Palmer: Why Ubuntu Loves dpatch

Joey, I strongly suspect that the reason that Ubuntu loves converting packages to use dpatch is because the version control tools that are being built in their secret workshops will be aimed around keeping patches separate, and it's reasonable to assume that Ubuntu will be heavily supporting the Wig-and-Pen dpkg source format, considering the originators of the format (and the fact that it looks like pretty decent technology).

Matthew Palmer: Debian Patch Management Smackdown

So, Joey Hess managed to stir up a bit of a discussion on the relative merits of patch management systems used in Debian packages. I guess it's a bit of a change from having this discussion on debian-mentors, at least... So I was thinking that it's time to really have a head-to-head of all of the methods that people have to manage their patches -- from the purpose-built systems, like dpatch and cdbs, to revision control systems and the scripts layered on top, to whatever personal processes various Developers may have. To assist in working out what to write, and to make comparisons a little more structured, I've jotted down a few ideas about what areas we might like to compare different systems against. So, tell us all your systems and why they work. Feel free to wax lyrical. Describe how your system works (even for the established programs, for people who aren't already familiar with the way they work), and describe how they match the areas above. I'd also be interested in hearing about systems you've tried and decided they weren't up to snuff. I'll be attempting to at least aggregate, if not summarise and combine, the opinions of everyone who contributes. If your blog is syndicated on Planet Debian, Just Blog It. Otherwise, either e-mail your ideas to me or send me a link to your blog or other page where your brainwaves are saved for posterity, and I'll include them in my "analysis".

Axel Beckert: Orpheus on Woody

Nobse’s blog posting about his ITP the text mode menu- and window-driven front-end to mpg123, mpg321 and ogg123 orpheus made me curious since I was also unsatisfied with the audio players I used so far and mostly ended up in using mpg123 -Z *.mp3, because it works fine and is not as resource-hungry as XMMS. And for CDs I usually used a self-written perl wrapper around the command line tools of cdtools (mostly cdir and cdplay). I first installed orpheus from sources on my SuSE box at work today while waiting for a windows box to upgrade to some service pack. At home I took nobse’s debian packages sources and recompiled the package on my Woody running desktop. After installing the required build dependecy dpatch from backports.org, the package compiled through without any problems and I now have a very useful and slim text mode audio player.
orpheus and aumix in transparent aterms
And orpheus and aumix look fine together inside transparent aterms.

Now playing in orpheus of course: Jean Michel Jarre — Je Me Souviens

Next.

Previous.